use super::{options::Options, Condition, ControlType, Size};
#[cfg(feature = "ssr")]
use crate::base::mysql::get_columns;
#[cfg(feature = "ssr")]
use crate::base::regex::is_exist_regex;
#[cfg(feature = "ssr")]
use crate::base::{Error, Result};
#[cfg(feature = "ssr")]
use crate::page_conf::valid_val_by_field_type;
use crate::prelude::DefaultValue;
use crate::structs::{FieldProps, FieldType};
use serde::{Deserialize, Serialize};

#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
pub struct EditProps {
    /** 控件类型 */
    #[serde(default)]
    pub control_type: ControlType,
    /** 初始化值 */
    #[serde(default)]
    pub init_val: Option<DefaultValue>,
    /** 是否多选用于select类型 */
    #[serde(default)]
    pub multiple: bool,
    /** 控件显示大小 */
    #[serde(default)]
    pub size: Size,
    /** 是否必须 */
    #[serde(default)]
    pub required: bool,
    /** 是否禁用控件 */
    pub disabled: Option<Condition>,
    /** 控件为空时的提示信息 */
    pub placeholder: Option<String>,
    /** 控件右上角的提示信息 */
    pub tooltip: Option<String>,
    /**校验规则：范围（最小值，最大值），对于字符串是最小长度和最大长度 */
    pub range_rule: Option<(isize, isize)>,
    /** 规则表达式（regex.yaml中配置的名称）*/
    pub regex_rule: Option<String>,
    /** 控件布局，24为整行，12为每行显示2个，8为每行显示3个；默认24 */
    #[serde(default = "grid_default")]
    pub grid: u8,
    /** 选项数据，当控件类型为Select和TreeSelect时需要*/
    pub options: Option<Options>,
    /** 是否在工具栏中以参数显示 */
    #[serde(default)]
    pub is_show_in_toolbar: bool,
    /** 是否编辑可见 */
    #[serde(default = "true_default")]
    pub is_editable: bool,
}
fn true_default() -> bool {
    true
}
impl Default for EditProps {
    fn default() -> Self {
        EditProps {
            control_type: ControlType::default(),
            init_val: None,
            multiple: false,
            size: Size::default(),
            required: false,
            disabled: None,
            placeholder: None,
            tooltip: None,
            range_rule: None,
            regex_rule: None,
            grid: grid_default(),
            options: None,
            is_show_in_toolbar: false,
            is_editable: false,
        }
    }
}

#[cfg(feature = "ssr")]
impl EditProps {
    pub async fn parse(&mut self, fp: &FieldProps) -> Result<()> {
        let ft = &fp.field_type;
        if let Some(opts) = self.options.as_mut() {
            if self.control_type != ControlType::Select
                && self.control_type != ControlType::TreeSelect
                && self.control_type != ControlType::Search
                && self.control_type != ControlType::CheckboxGroup
                && self.control_type != ControlType::RadioGroup
                && self.control_type != ControlType::TextInput
                && self.control_type != ControlType::Search
            {
                return Err(Error::Conf(format!(
                    "edit_props配置control_type:{:?}不支持options",
                    &self.control_type
                )));
            }
            match ft {
                FieldType::Bool
                | FieldType::Date
                | FieldType::Datetime
                | FieldType::Float32
                | FieldType::Float64 => {
                    return Err(Error::Conf(format!("字典标注不支持数据类型{:?}", ft)));
                }
                _ => {}
            }
            let mut fetch_table_cols:Vec<FieldProps>=Vec::new();
            match opts {
                Options::Array(vec) => {
                    if vec.is_empty() {
                        return Err(Error::Conf(format!(
                            "{}控件的options配置Array为空",
                            self.control_type
                        )));
                    }
                    self.control_type = ControlType::Select;
                }
                Options::Map(vec) => {
                    if vec.is_empty() {
                        return Err(Error::Conf(format!(
                            "{}控件的options配置Map为空",
                            self.control_type
                        )));
                    }
                    self.control_type = ControlType::Select;
                }
                Options::Tree(vec) => {
                    if vec.is_empty() {
                        return Err(Error::Conf(format!(
                            "{}控件的options配置Tree为空",
                            self.control_type
                        )));
                    }
                    self.control_type = ControlType::TreeSelect;
                }
                Options::Fetch(fetch_params) => {
                    if fetch_params.table_name.is_empty() {
                        return Err(Error::Conf(format!(
                            "edit_props配置options-table_name不能为空"
                        )));
                    }
                    if fetch_params.label_col.is_empty() {
                        return Err(Error::Conf(format!(
                            "edit_props配置options-label_col不能为空"
                        )));
                    }
                    if fetch_params.value_col.is_empty() {
                        return Err(Error::Conf(format!(
                            "edit_props配置options-value_col不能为空"
                        )));
                    }
                    let cols = get_columns(fetch_params.table_name.as_str())
                        .await
                        .map_err(|err| Error::Conf(format!("获取columns出错:{err}")))?;
                    if cols.is_empty() {
                        return Err(Error::Conf(format!(
                            "edit_props配置options-table_name:{}不存在",
                            fetch_params.table_name
                        )));
                    }
                    if !cols.iter().any(|f| f.name == fetch_params.label_col) {
                        return Err(Error::Conf(format!(
                            "edit_props配置options-label_col:{}在表{}中不存在",
                            fetch_params.label_col, &fetch_params.table_name
                        )));
                    }
                    if !cols.iter().any(|f| f.name == fetch_params.value_col) {
                        return Err(Error::Conf(format!(
                            "edit_props配置options-value_col:{}在表{}中不存在",
                            fetch_params.value_col, &fetch_params.table_name
                        )));
                    }
                    if fetch_params.search_cols.is_some() {
                        if fetch_params.search_cols.as_ref().unwrap().is_empty() {
                            return Err(Error::Conf(format!(
                                "edit_props配置options-search_cols不能为空"
                            )));
                        }
                        for col in fetch_params.search_cols.as_ref().unwrap().iter() {
                            if !cols.iter().any(|f| f.name == *col) {
                                return Err(Error::Conf(format!(
                                    "edit_props配置options-search_cols:{}在表{}中不存在",
                                    col, &fetch_params.table_name
                                )));
                            }
                        }
                        self.control_type = ControlType::Search;
                    } else if fetch_params.parent_col.is_some() {
                        if fetch_params.parent_col.as_ref().unwrap().is_empty() {
                            return Err(Error::Conf(format!(
                                "edit_props配置options-parent_col不能为空"
                            )));
                        }
                        let pcol = fetch_params.parent_col.as_deref().unwrap();
                        if !cols.iter().any(|f| f.name.as_str() == pcol) {
                            return Err(Error::Conf(format!(
                                "edit_props配置options-parent_col:{}在表{}中不存在",
                                pcol, &fetch_params.table_name
                            )));
                        }
                        self.control_type = ControlType::TreeSelect;
                    }
                    fetch_table_cols=cols;
                }
            }
            opts.parse(&fetch_table_cols)
                .await
                .map_err(|err| Error::Conf(format!("验证options出错:{err}")))?;
        }
        if self.multiple {
            if let FieldType::String(_) = ft {
                return Err(Error::Conf(format!(
                    "edit_props配置multiple多选的数据类型必须是String，当前类型为{:?}",
                    ft
                )));
            }
            if self.control_type != ControlType::Select
                && self.control_type != ControlType::CheckboxGroup
            {
                return Err(Error::Conf(format!(
                    "edit_props配置控件类型{:?}不支持多选，请使用Select或者CheckboxGroup",
                    self.control_type
                )));
            }
        }
        if !self.required && !fp.is_null && !fp.is_pk {
            return Err(Error::Conf(format!(
                "edit_props配置字段{}的required为false，但数据库字段为not null",
                fp.name
            )));
        }
        if let Some(init_val) = self.init_val.as_ref() {
            let dv=init_val.get_value().await?;
            valid_val_by_field_type(*ft, &dv).or_else(|err| {
                Err(Error::Conf(format!(
                    "edit_props配置init_val:{:?}类型不匹配，当前类型为{:?}，错误信息：{}",
                    init_val, ft, err
                )))
            })?;
        }
        if let Some(regex) = self.regex_rule.as_ref() {
            if !is_exist_regex(regex) {
                return Err(Error::Conf(format!(
                    "edit_props配置regex_rule:{:?}在配置regex.yaml中不存在",
                    regex
                )));
            }
        }
        match self.control_type {
            ControlType::Select
            | ControlType::TreeSelect
            | ControlType::RadioGroup
            | ControlType::CheckboxGroup => {
                if let Some(opt) = self.options.as_ref() {
                    match opt {
                        Options::Array(vec) => {
                            if vec.is_empty() {
                                return Err(Error::Conf(format!(
                                    "{}控件的options配置Array为空",
                                    self.control_type
                                )));
                            }
                        }
                        Options::Map(vec) => {
                            if vec.is_empty() {
                                return Err(Error::Conf(format!(
                                    "{}控件的options配置Map为空",
                                    self.control_type
                                )));
                            }
                        }
                        Options::Tree(vec) => {
                            if vec.is_empty() {
                                return Err(Error::Conf(format!(
                                    "{}控件的options配置Tree为空",
                                    self.control_type
                                )));
                            }
                        }
                        Options::Fetch(f) => {
                            f.parse().await.or_else(|e| {
                                Err(Error::Conf(format!("options配置Fetch有误:{}", e)))
                            })?;
                        }
                    }
                } else {
                    return Err(Error::Conf(format!(
                        "{}控件必须指定options",
                        self.control_type
                    )));
                }
            }
            ControlType::Search => {
                if let Some(opt) = self.options.as_ref() {
                    match opt {
                        Options::Fetch(f) => {
                            f.parse().await.or_else(|e| {
                                Err(Error::Conf(format!("options配置Fetch有误:{}", e)))
                            })?;
                            if let Some(scols) = f.search_cols.as_ref() {
                                if scols.is_empty() {
                                    return Err(Error::Conf(format!(
                                        "{}控件的options必须指定为Fetch，且search_cols不为空",
                                        self.control_type
                                    )));
                                }
                            } else {
                                return Err(Error::Conf(format!(
                                    "{}控件的options必须指定为Fetch，且必须指定search_cols",
                                    self.control_type
                                )));
                            }
                        }
                        _ => {
                            return Err(Error::Conf(format!(
                                "{}控件必须的options必须指定为Fetch",
                                self.control_type
                            )));
                        }
                    }
                } else {
                    return Err(Error::Conf(format!(
                        "{}控件必须指定options",
                        self.control_type
                    )));
                }
            }
            _ => {
                if self.options.is_some() {
                    return Err(Error::Conf(format!(
                        "{}控件不能指定options",
                        self.control_type
                    )));
                }
            }
        }
        match self.control_type {
            ControlType::TextInput => match ft {
                FieldType::Bool => {
                    self.control_type = ControlType::Checkbox;
                    Ok(())
                }
                FieldType::Date => {
                    self.control_type = ControlType::Date;
                    Ok(())
                }
                FieldType::Datetime => {
                    self.control_type = ControlType::Datetime;
                    Ok(())
                }
                FieldType::Int8
                | FieldType::Int16
                | FieldType::Int32
                | FieldType::Int64
                | FieldType::UInt8
                | FieldType::UInt16
                | FieldType::UInt32
                | FieldType::UInt64 => {
                    self.control_type = ControlType::IntegerInput;
                    Ok(())
                }
                FieldType::Float32 | FieldType::Float64 => {
                    self.control_type = ControlType::DecimalInput;
                    Ok(())
                }
                _ => Ok(()),
            },
            ControlType::DecimalInput => {
                if matches!(*ft, FieldType::Float32 | FieldType::Float64 | FieldType::Decimal(_, _))
                {
                    Ok(())
                } else {
                    Err(Error::Conf(format!(
                        "控件类型DecimalInput不支持数据类型{:?}",
                        ft
                    )))
                }
            }
            ControlType::IntegerInput => match ft {
                FieldType::Int8
                | FieldType::Int16
                | FieldType::Int32
                | FieldType::Int64
                | FieldType::UInt8
                | FieldType::UInt16
                | FieldType::UInt32
                | FieldType::UInt64 => Ok(()),
                _ => {
                    return Err(Error::Conf(format!(
                        "控件类型IntegerInput不支持数据类型{:?}",
                        ft
                    )))
                }
            },
            ControlType::AlphaInput | ControlType::AlphanumInput => {
                if let FieldType::String(_) = *ft {
                    Ok(())
                } else {
                    Err(Error::Conf(format!(
                        "控件类型{:?}不支持数据类型{:?}",
                        self.control_type, ft
                    )))
                }
            }
            ControlType::Year
            | ControlType::Quarter
            | ControlType::Month
            | ControlType::Time
            | ControlType::Select
            | ControlType::TreeSelect
            | ControlType::RadioGroup
            | ControlType::Search => match ft {
                FieldType::Int8
                | FieldType::Int16
                | FieldType::Int32
                | FieldType::Int64
                | FieldType::UInt8
                | FieldType::UInt16
                | FieldType::UInt32
                | FieldType::UInt64
                | FieldType::String(_) => Ok(()),
                _ => Err(Error::Conf(format!(
                    "控件类型{:?}不支持数据类型{:?}",
                    self.control_type, ft
                ))),
            },
            ControlType::Date => match ft {
                FieldType::Date => Ok(()),
                _ => Err(Error::Conf(format!(
                    "控件类型{:?}不支持数据类型{:?}",
                    self.control_type, ft
                ))),
            },
            ControlType::Datetime => match ft {
                FieldType::Datetime => Ok(()),
                _ => Err(Error::Conf(format!(
                    "控件类型{:?}不支持数据类型{:?}",
                    self.control_type, ft
                ))),
            },
            ControlType::Checkbox => match ft {
                FieldType::Bool => Ok(()),
                _ => Err(Error::Conf(format!(
                    "指定的ControlType::Month不支持数据类型{:?}",
                    ft
                ))),
            },
            ControlType::CheckboxGroup => match ft {
                FieldType::String(_) => Ok(()),
                _ => Err(Error::Conf(format!(
                    "指定的ControlType::Month不支持数据类型{:?}",
                    ft
                ))),
            },
            ControlType::Textarea => match ft {
                FieldType::String(_) => Ok(()),
                _ => Err(Error::Conf(format!(
                    "控件类型{:?}不支持数据类型{:?}",
                    self.control_type, ft
                ))),
            },
        }
    }
}
fn grid_default() -> u8 {
    3
}
